using System;
using System.Linq.Expressions;

namespace Columbus.ActionResults
{
    /// <summary>
    /// Redirect result is returned to navigate to any action of any controller 
    /// </summary>
    public class RedirectResult : ActionResult
    {
        private readonly string controllerName;
        private readonly string actionName;
        private readonly NavigationContext context;
        private readonly object[] parameters;

        /// <summary>
        /// Initializes a new instance of the <see cref="RedirectResult"/> class.
        /// </summary>
        /// <param name="controllerName">Name of controller.</param>
        /// <param name="actionName">Name of action.</param>
        /// <param name="context">Navigation context.</param>
        /// <param name="parameters">Parameters.</param>
        public RedirectResult(string controllerName, string actionName, NavigationContext context, params object[] parameters)
            : base(context)
        {
            this.controllerName = controllerName;
            this.actionName = actionName;
            this.context = context;
            this.parameters = parameters;
        }

        /// <summary>
        /// Executes result.
        /// </summary>
        protected override void ExecuteInternal()
        {
            context.Navigator.NavigateTo(controllerName, actionName, parameters);
        }
    }

    /// <summary>
    /// Redirect result is returned to navigate to any action of any controller 
    /// </summary>
    public class RedirectResult<TController> : ActionResult 
        where TController : Controller
    {
        private readonly Expression<Func<TController, ActionResult>> actionSelector;
        private readonly NavigationContext context;

        /// <summary>
        /// Initializes a new instance of the <see cref="RedirectResult&lt;TController&gt;"/> class.
        /// </summary>
        /// <param name="actionSelector">Action selector.</param>
        /// <param name="context">Navigation context.</param>
        public RedirectResult(Expression<Func<TController, ActionResult>> actionSelector, NavigationContext context)
            : base(context)
        {
            this.actionSelector = actionSelector;
            this.context = context;
        }

        /// <summary>
        /// Executes result.
        /// </summary>
        protected override void ExecuteInternal()
        {
            context.Navigator.NavigateTo(actionSelector);
        }
    }
}